package com.firemoss.ui.blanket.components
{
	import com.firemoss.ui.blanket.AbstractBlanketOverlay;
	import com.firemoss.ui.blanket.IBlanketDisplayObjectContainerLocator;
	import com.firemoss.ui.blanket.calloutClasses.*;
	
	import flash.display.DisplayObjectContainer;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	
	import mx.core.IMXMLObject;
	import mx.core.UIComponent;
	import mx.events.FlexEvent;
	
	/**
	 * Wraps an AbstractBlanketOverlay instance to allow it to be used as an MXML component outside of
	 * display list.
	 */
	public class AbstractOverlayComponent extends EventDispatcher implements IMXMLObject
	{
		
		// PRIVATE PROPERTIES
		
		/**
		 * The overlay component.
		 */
		protected var view : AbstractBlanketOverlay
		
		// PUBLIC PROPERTIES
		
		public function set target( value : UIComponent ) : void
		{
			if ( view.target )
			{
				view.target.removeEventListener( FlexEvent.CREATION_COMPLETE, targetCreated )
				removeParentUIComponentEventListeners( view.target )
			}
			
			view.target = value

			if ( target.initialized )
			{
				targetCreated()
			}
			else
			{
				value.addEventListener( FlexEvent.CREATION_COMPLETE, targetCreated, false, 0, true )
			}
		}
		public function get target() : UIComponent
		{
			return view.target
		}
		
		private var _visible : Boolean
		public function set visible( value : Boolean ) : void
		{
			if ( !_visible && value && view && target )
			{
				showView()
			}
			
			if ( _visible && !value && view && target )
			{
				hideView()
			} 
			
			_visible = value
		}
		public function get visible() : Boolean
		{
			return _visible
		}
		
		public function get containerLocator() : IBlanketDisplayObjectContainerLocator
		{
			return view.containerLocator ? view.containerLocator : null
		}
		
		public function set containerLocator( value : IBlanketDisplayObjectContainerLocator ) : void
		{
			if (view)
			{
				view.containerLocator = value
			}
		}
		
		public function get showSource() : IEventDispatcher
		{
			return view.showSource ? view.showSource : null
		}
		
		public function set showSource( value : IEventDispatcher ) : void
		{
			if (view)
			{
				view.showSource = value
			}
		}
		
		public function get hideSource() : IEventDispatcher
		{
			return view.hideSource ? view.hideSource : null
		}
		
		public function set hideSource( value : IEventDispatcher ) : void
		{
			if (view)
			{
				view.hideSource = value
			}
		}
		
		public function get showEvent() : String
		{
			return view.showEvent ? view.showEvent : null
		}
		
		public function set showEvent( value : String ) : void
		{
			if (view)
			{
				view.showEvent = value
			}
		}
		
		public function get hideEvent() : String
		{
			return view.hideEvent ? view.hideEvent : null
		}
		
		public function set hideEvent( value : String ) : void
		{
			if (view)
			{
				view.hideEvent = value
			}
		}
		
		// PRIVATE METHODS
		
		private function showView() : void
		{
			view.show()
		}
		
		private function hideView() : void
		{
			view.hide()
		}
		
		// PUBLIC METHODS
		
		public function initialized(document:Object, id:String):void
		{
			if ( document is UIComponent)
			{
				UIComponent( document ).addEventListener( FlexEvent.CREATION_COMPLETE, documentCreated, false, 0, true )
			}
		}

		public function showImmediately() : void
		{
			view.show( true )
		}
		
		public function hideImmediately() : void
		{
			view.hide( true )
		}
		
		// EVENT HANDLERS
		
		private function documentCreated( event : FlexEvent ) : void
		{
			UIComponent( event.target ).removeEventListener( FlexEvent.CREATION_COMPLETE, documentCreated )
			
			if (visible && view && target && target.systemManager)
			{
				showView()
			}
		}

		private function targetCreated( event : FlexEvent = null ) : void
		{
			if (visible)
			{
				showView()
			}
			
			addParentUIComponentEventListeners( view.target )
		}

		private function addParentUIComponentEventListeners( parent : DisplayObjectContainer ) : void
		{
			parent.addEventListener( FlexEvent.HIDE, parentUIComponentHidden, false, 0, true )
			parent.addEventListener( FlexEvent.SHOW, parentUIComponentShown, false, 0, true )
			
			if ( parent.parent )
			{
				addParentUIComponentEventListeners( parent.parent )
			}
		}
		
		private function removeParentUIComponentEventListeners( parent : DisplayObjectContainer ) : void
		{
			parent.removeEventListener( FlexEvent.HIDE, parentUIComponentHidden )
			parent.removeEventListener( FlexEvent.SHOW, parentUIComponentShown )
			
			if ( parent.parent )
			{
				removeParentUIComponentEventListeners( parent.parent )
			}
		}
		
		private function parentUIComponentHidden( event : FlexEvent ) : void
		{
			hideImmediately()
		}
		
		private function parentUIComponentShown( event : FlexEvent ) : void
		{
			if ( visible )
			{
				showImmediately()
			}
		}

	}
}